package ljl.alg.wangzheng_camp.round1.stack_and_queue;

import java.util.Deque;
import java.util.LinkedList;

public class _16_26_calculator {
    
    /**
     *
     * 我这个解法太傻屄了，没法弄
     * */
    String s;
    int pos;
    Deque<Integer> numberStack = new LinkedList<>();
    Deque<Character> opStack = new LinkedList<>();
    public int calculate(String s) {
        this.s = s;
        while (pos < s.length()) {
            String token = next();
            if (token == null) break;
            char c = token.charAt(0);
            // 这两个应该都能导致它开始计算
            // 一个数，发现前面是 * / 开始算；发现前面是 + - 还得等等，防止后面是 * /
            // 一个符号，自己是 + -，前面是 + -，前面可以算一次；自己是乘除，入栈，后面有 vip
            if (Character.isDigit(token.charAt(0))) {
                numberStack.push(Integer.parseInt(token));
                if (numberStack.size() > 1 && shouldCalc('\0', opStack.peek()))
                    calc();
            }
            else {
                if (numberStack.size() > 1 && shouldCalc(c, '\0')) {
                    calc();
                }
                opStack.push(c);
            }
        }
        while (!opStack.isEmpty())
            calc();
        
        return numberStack.peek();
    }
    void calc () {
        char op = opStack.pop();
        int operand1 = numberStack.pop();
        int operand2 = numberStack.pop();
        numberStack.push(calc(op, operand2, operand1));
    }
    int calc(char op, int operand1, int operand2) {
        return switch (op) {
            case '+' -> operand1 + operand2;
            case '-' -> operand1 - operand2;
            case '*' -> operand1 * operand2;
            case '/' -> operand1 / operand2;
            default -> 0;
        };
    }
    boolean shouldCalc(char cur, char prev) {
        return prev == '*' || prev == '/' || cur == '+' || cur == '-';
    }
    String next() {
        while (pos < s.length() && s.charAt(pos) == ' ')
            pos++;
        if (pos == s.length())
            return null;
        char c = s.charAt(pos++);
        if (c == '+' || c == '-' || c == '*' || c == '/') return String.valueOf(c);
        int start = pos - 1;
        while (pos < s.length() && Character.isDigit(s.charAt(pos)))
            pos++;
        return s.substring(start, pos);
    }
    
    /**
     * 没有括号
     * 保证是合法表达式
     *
     * 导致了这个代码的样子
     * */
    class Solution2 {
        
        public int calculate(String s) {
            char[] cs = s.trim().toCharArray();
            Deque<Integer> st = new LinkedList<>();
            int ans = 0, i = 0;
            while(i < cs.length){
                if(cs[i] == ' ') {i++;continue;}
                char tmp = cs[i];
                if(tmp == '*' || tmp == '/' || tmp == '+' || tmp == '-'){
                    i++;
                    while(i < cs.length && cs[i] == ' ') i++;
                }
                int num = 0;
                while(i < cs.length && Character.isDigit(cs[i])){
                    num = num * 10 + cs[i] - '0';
                    i++;
                }
                // 乘除当场处理了
                // 负号也是，作为一个整体入栈
                switch(tmp){
                    case '-':
                        num = -num;
                        break;
                    case '*':
                        num = st.pop() * num;
                        break;
                    case '/':
                        num = st.pop() / num;
                        break;
                    default:
                        break;
                }
                st.push(num);
            }
            while(!st.isEmpty()) ans += st.pop();
            return ans;
        }
    }
    
    /**
     * 我来抄一遍人家的答案吧
     * 没几个会的
     *
     * 比我快，但这不是我想要的答案，就这吧
     *
     * */
    class Solution3 {
        public int calculate(String s) {
            s = s.trim();
            Deque<Integer> stack = new LinkedList<>();
            int i = 0;
            int res = 0;
            while (i < s.length()) {
                while (i < s.length() && s.charAt(i) == ' ') i++;
                char op = s.charAt(i);
                if (op == '+' || op == '-' || op == '*' || op == '/') {
                    i++;
                    while (i < s.length() && s.charAt(i) == ' ') i++;
                }
                char c = s.charAt(i);
                int num = c - '0';
                while (++i < s.length() && Character.isDigit(c = s.charAt(i)))
                    num = num * 10 + c - '0';
        
                switch (op) {
                    case '-' -> num = -num;
                    case '*' -> num *= stack.pop();
                    case '/' -> num = stack.pop() / num;
                }
                stack.push(num);
            }
            while (!stack.isEmpty()) res += stack.pop();
            return res;
        }
    }
    
}
